#include "stdTcpServer.h"
#include <iostream>

using namespace std;

#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <json-c/json.h>


/* 无参构造 */
StdTcpServer::StdTcpServer() : m_tcpAttr(make_unique<stdTcpServerPrivate>())
{
    m_tcpAttr->m_sockfd = -1;
    m_tcpAttr->m_isRunning = false;
}

/* 析构函数 */
StdTcpServer::~StdTcpServer()
{
    if(m_tcpAttr->m_sockfd > 0)
    {
        close(m_tcpAttr->m_sockfd);
    }

}

/* 设置监听 */
bool StdTcpServer::setListen(int port)
{
    /* 类内部维护端口信息 */
    this->m_port = port;

    /* 创建套接字 */
    m_tcpAttr->m_sockfd =  socket(AF_INET, SOCK_STREAM, 0);
    if(m_tcpAttr->m_sockfd == -1)
    {
        perror("sockfd error:");
        // 不能退出，服务器不允许退出，可以抛异常
        throw runtime_error("socket create failed");
    }
    /* 设置端口复用，当先结束server时候，由于四次挥手的timewait，server会持续占用端口，2分钟之后才会断开 */
    int optVal = 1;
    int ret = setsockopt(m_tcpAttr->m_sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
    if(ret != 0)
    {
        perror("setsockopt error");
        // 抛异常和设置返回值都可以 
        return false;
    }

    /* 绑定IP和端口信息 */
    struct sockaddr_in localAddress;
    /* 清空结构体的脏数据 */
    memset(&localAddress, 0, sizeof(localAddress));
    /* 地址族设置为IPV4 */
    localAddress.sin_family = AF_INET;
    /* 把主机字节序转为网络 */
    localAddress.sin_port = htons(m_port);
    /* 设置全通规则 */
    localAddress.sin_addr.s_addr = htonl(INADDR_ANY);

    ret = bind(m_tcpAttr->m_sockfd, reinterpret_cast<struct sockaddr*>(&localAddress), sizeof(localAddress));
    if(ret != 0)
    {
        perror("bind error");
        throw runtime_error("bind failed");
    }
    /* 设置监听 */
    ret = listen(m_tcpAttr->m_sockfd, 0);
    if(ret != 0)
    {
        perror("listen error");
        throw runtime_error("listen failed");
    }

    m_tcpAttr->m_isRunning = true;

    return true;
}

/* 接收客户端的连接 */
std::shared_ptr<StdTcpSocket> StdTcpServer::getClientSock()
{
    int clientConnfd = accept(m_tcpAttr->m_sockfd, NULL, NULL);
    if(clientConnfd == -1)
    {
        perror("accept error:");
        throw std::runtime_error("accept failed");
    }
    /* 客户端连接成功 */
    cout << clientConnfd << "客户端连接成功"  << endl;
    
    
    /* 通信类 */
    auto client = std::make_shared<StdTcpSocket>();
    if (!client || !client->getSockAttr()) 
    {
        throw std::runtime_error("Failed to initialize StdTcpSocket or its attributes");
    }

    /* 套接字 */
    client->getSockAttr()->connfd = clientConnfd;
    client->getSockAttr()->m_connected = true;

    return client;
}

/*--------------通信类--------------*/

/* 构造函数 */
StdTcpSocket::StdTcpSocket():m_sockAttr(std::make_unique<stdTcpSocketPrivate>())
{
    m_sockAttr->connfd = -1;
    m_sockAttr->m_connected = false;
}

/* 析构函数 */
StdTcpSocket::~StdTcpSocket()
{
    if(m_sockAttr->connfd > 0)
    {
        /* 回收资源 */
        close(m_sockAttr->connfd);
    }
}

/* 连接服务器 */
int StdTcpSocket::connectToServer(const char *ip, int port)
{
    /* 创建套接字 */
    int sockfd =  socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("sockfd error:");
        exit(-1);
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &(serverAddr.sin_addr.s_addr));

    int ret = connect(sockfd, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr));
    if(ret != 0)
    {
        perror("connect error:");
        return -1;
    }
    cout << "服务器连接成功" << endl;

    m_sockAttr->connfd = sockfd;
    m_sockAttr->m_connected = true;

    return 0;
}

/* 是否连接成功 */
bool StdTcpSocket::isConnected() const
{
    return m_sockAttr->m_connected;
}

/* 发送数据 */
int StdTcpSocket::sendMessage(const std::string &sendMsg)
{
    return sendMessage(sendMsg.c_str(), sendMsg.size());
}

/* 发送数据 */
int StdTcpSocket::sendMessage(const void *sendMsg, size_t n)
{
    /* 解决前后包粘包问题 */
    /* 1. 先发数据包的大小 */
    int writeBytes = write(m_sockAttr->connfd, (const void *)&n, sizeof(n));
    if(writeBytes < 0)
    {
        perror("write size error:");
        return -1;
    }
    /* 2. 再写数据本身 */
    writeBytes = write(m_sockAttr->connfd, sendMsg, n);
    if(writeBytes < 0)
    {
        perror("write error:");
        return -1;
    }

    return writeBytes;
}


/* 接收数据 */
int StdTcpSocket::recvMessage(std::string &recvMsg)
{
    if (!m_sockAttr || m_sockAttr->connfd < 0) 
    {
        std::cerr << "Error: invalid socket attributes" << std::endl;
        return -1;
    }

    size_t size = 0;
    /* 获得后面数据的长度 */
    int readBytes = read(m_sockAttr->connfd, (void *)&size, sizeof(size_t));
    if(readBytes <= 0)
    {
        perror("read error:");
        return -1;
    }

    char *msg = new char[size + 1];
    /* 清理脏数据 */
    memset(msg, 0, sizeof(char)*(size + 1));

    int totalReceived = 0;
    while(totalReceived < size)
    {
        size_t received = read(m_sockAttr->connfd, msg + totalReceived, size - totalReceived);
        if(received < 0)
        {
            perror("read error:");
            delete [] msg;
            return -1;
        }
        totalReceived += received;
    }
    /* 接收到的数据*/
    recvMsg = msg;
    delete [] msg;

    return totalReceived;
}

/* 接收数据 */
int StdTcpSocket::recvMessage(void *buf, size_t n)
{
    
    return read(m_sockAttr->connfd, buf, n);
}

stdTcpSocketPrivate *StdTcpSocket::getSockAttr() const
{
    //智能指针get函数获得原始指针
     if (!m_sockAttr) {
        std::cerr << "Error: m_sockAttr is nullptr!" << std::endl;
        return nullptr;
    }
    return m_sockAttr.get();
} 
